package topcbl.util;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import com.google.android.gms.maps.model.LatLng;

import topcbl.taxi.R;

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

/**
 * Create this Class from tutorial :
 * http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial
 * 
 * For Geocoder read this :
 * http://stackoverflow.com/questions/472313/android-reverse
 * -geocoding-getfromlocation
 * 
 */

public class GPSTracker extends Service implements LocationListener {
	private final Context mContext;

	// flag for GPS Status
	boolean isGPSEnabled = false;

	// flag for network status
	boolean isNetworkEnabled = false;

	Location location;
	double latitude;
	double longitude;

	// The minimum distance to change updates in metters
	private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10
																	// metters

	// The minimum time between updates in milliseconds
	private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

	// Declaring a Location Manager
	protected LocationManager locationManager;

	public GPSTracker(Context context) {
		this.mContext = context;
		getLocation();
		updateGPSCoordinates();
	}

	public Location getLocation() {
		locationManager = (LocationManager) mContext
				.getSystemService(LOCATION_SERVICE);

		// getting GPS status
		isGPSEnabled = locationManager
				.isProviderEnabled(LocationManager.GPS_PROVIDER);

		// getting network status
		isNetworkEnabled = locationManager
				.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

		if (isNetworkEnabled) {
			locationManager.requestLocationUpdates(
					LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES,
					MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

			Log.d("topcbl", "Network");

			if (locationManager != null) {
				location = locationManager
						.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
			}
		}

		// if GPS Enabled get lat/long using GPS Services
		if (isGPSEnabled) {
			if (location == null) {
				locationManager.requestLocationUpdates(
						LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES,
						MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

				Log.d("topcbl", "GPS Enabled");

				if (locationManager != null) {
					location = locationManager
							.getLastKnownLocation(LocationManager.GPS_PROVIDER);
				}
			}
		}
		return location;
	}

	public void setLocation(LatLng point) {
		latitude = point.latitude;
		longitude = point.longitude;
	}

	public LatLng getLatLngCurrent() {
		return new LatLng(latitude, longitude);
	}

	public void updateGPSCoordinates() {
		if (location != null) {
			latitude = location.getLatitude();
			longitude = location.getLongitude();
		}
	}

	/**
	 * Stop using GPS listener Calling this function will stop using GPS in your
	 * app
	 */

	public void stopUsingGPS() {
		if (locationManager != null) {
			locationManager.removeUpdates(GPSTracker.this);
		}
	}

	/**
	 * Function to get latitude
	 */
	public double getLatitude() {
		return latitude;
	}

	/**
	 * Function to get longitude
	 */
	public double getLongitude() {
		return longitude;
	}

	/**
	 * Function to check GPS/wifi enabled
	 */
	public boolean canGetLocation() {
		if (!isGPSEnabled && !isNetworkEnabled)
			return false;
		else
			return true;
	}

	/**
	 * Function to show settings alert dialog
	 */
	public void showSettingsAlert() {
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

		// Setting Dialog Title
		alertDialog.setTitle(R.string.GPSAlertDialogTitle);

		// Setting Dialog Message
		alertDialog.setMessage(R.string.GPSAlertDialogMessage);

		// On Pressing Setting button
		alertDialog.setPositiveButton(R.string.settings,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Intent intent = new Intent(
								Settings.ACTION_LOCATION_SOURCE_SETTINGS);
						mContext.startActivity(intent);
					}
				});

		// On pressing cancel button
		alertDialog.setNegativeButton(R.string.cancel,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				});

		alertDialog.show();
	}

	/**
	 * Get list of address by latitude and longitude
	 * 
	 * @return null or List<Address>
	 */
	public List<Address> getGeocoderAddress(Context context) {
		Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
		try {
			List<Address> addresses = geocoder.getFromLocation(latitude,
					longitude, 1);
			return addresses;
		} catch (IOException e) {
			// e.printStackTrace();
			Log.e("Error : Geocoder", "Impossible to connect to Geocoder", e);
		}
		return null;
	}

	/**
	 * Try to get AddressLine
	 * 
	 * @return null or addressLine
	 */
	public String getAddressLine(Context context) {
		List<Address> addresses = getGeocoderAddress(context);
		if (addresses != null && addresses.size() > 0) {
			Address address = addresses.get(0);
			String addressLine = "";
			for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
				addressLine += address.getAddressLine(i) + ", ";
			}
			return addressLine.substring(0, addressLine.length() - 2);
		} else {
			return null;
		}
	}

	/**
	 * Try to get Locality
	 * 
	 * @return null or locality
	 */
	public String getLocality(Context context) {
		List<Address> addresses = getGeocoderAddress(context);
		if (addresses != null && addresses.size() > 0) {
			Address address = addresses.get(0);
			String locality = address.getLocality();

			return locality;
		} else {
			return null;
		}
	}

	/**
	 * Try to get Postal Code
	 * 
	 * @return null or postalCode
	 */
	public String getPostalCode(Context context) {
		List<Address> addresses = getGeocoderAddress(context);
		if (addresses != null && addresses.size() > 0) {
			Address address = addresses.get(0);
			String postalCode = address.getPostalCode();

			return postalCode;
		} else {
			return null;
		}
	}

	/**
	 * Try to get CountryName
	 * 
	 * @return null or postalCode
	 */
	public String getCountryName(Context context) {
		List<Address> addresses = getGeocoderAddress(context);
		if (addresses != null && addresses.size() > 0) {
			Address address = addresses.get(0);
			String countryName = address.getCountryName();

			return countryName;
		} else {
			return null;
		}
	}

	@Override
	public void onLocationChanged(Location location) {
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	public static List<Address> getCoordinateFromAddress(String strAddress,
			Context context) {
		Geocoder coder = new Geocoder(context);
		List<Address> address;
		try {
			address = coder.getFromLocationName(strAddress, 5);
			if (address == null) {
				Log.i("topcbl", "recognize position by name: FAULT " + "???");
				return null;
			}
			return address;
		} catch (Exception e) {
			Log.i("topcbl",
					"recognize position by name: FAULT " + e.getMessage());
			return null;
		}
	}

	public static String getAddressFromCoordinate(double lat, double lng,
			Context context) {
		Geocoder geocoder = new Geocoder(context, Locale.ENGLISH);
		try {
			List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);
			if (addresses != null && addresses.size() > 0) {
				Address address = addresses.get(0);
				String addressLine = "";
				for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
					addressLine += address.getAddressLine(i) + ", ";
				}
				return addressLine.substring(0, addressLine.length() - 2);
			} else {
				return null;
			}
		} catch (IOException e) {
			// e.printStackTrace();
			Log.e("Error : Geocoder", "Impossible to connect to Geocoder", e);
			return null;
		}

	}
}